﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using Eflong.Utility;

namespace Eflong.KJFiles
{
    public class FileBackup : IFileBackup
    {
        public static SortedDictionary<string , DateTime> DicFiles = new SortedDictionary<string , DateTime>( );

        public static string[ ] BackupDirs = new string[ ] { "backup0" , "backup1" , "backup2" , "backup3" , "backup4" , "backup5" , "backup6" , "backupdev" };

        private static string _backupDir;

        private static int _currDir = -1;

        public FileBackup( )
            : this( @"d:\databackup" )
        {
        }

        public FileBackup( string baseDir )
        {
            _backupDir = baseDir;
            _currDir = GetBackupDir( DateTime.Now );

            foreach ( var dir in BackupDirs )
            {
                string path = _backupDir + @"\" + dir;
                if ( !Directory.Exists( path ) )
                {
                    Directory.CreateDirectory( path );
                }
            }
        }

        /// <summary>
        /// 备份文件
        /// </summary>
        /// <param name="fileName"></param>
        public void BackupFile( string fileName )
        {
            BackupFile( fileName , true );
        }

        /// <summary>
        /// 备份文件
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <param name="isDataFile">是否数据文件</param>
        public void BackupFile( string fileName , bool isDataFile )
        {
            if ( File.Exists( fileName ) )
            {
                try
                {
                    var time = File.GetLastWriteTime( fileName );
                    if ( isDataFile )
                    {
                        var dir = GetBackupDir( time );
                        if ( dir != _currDir )
                        {
                            _currDir = dir;
                            DeleteOverdueFiles( dir );
                        }
                        var bkFileName = GetBackupFileName( fileName , time , dir );
                        File.Copy( fileName , bkFileName );
                    }
                    else
                    {
                        var bkFileName = GetDevBackupFileName( fileName , time );
                        File.Copy( fileName , bkFileName );
                    }
                }
                catch ( Exception ex )
                {
                    LogWrapper.Logger.Error( " BackupFile Error : " + ex.Message );
                }
            }
        }

        /// <summary>
        /// 获取文件应该保存的目录的索引
        /// </summary>
        /// <param name="fileTime"></param>
        /// <returns></returns>
        public int GetBackupDir( DateTime fileTime )
        {
            var day = ( int )fileTime.DayOfWeek;

            return ValidDay( day );
        }

        private static int ValidDay( int day )
        {
            return day >= 7 ? 0 : day;
        }

        public string GetBackupFileName( string fileName , DateTime fileTime , int index )
        {
            return _backupDir + @"\" + BackupDirs[ index ] + @"\" + Path.GetFileName( fileName ) + fileTime.ToString( ".yyyyMMddHHmmss.bak" );
        }

        public string GetDevBackupFileName( string fileName , DateTime fileTime )
        {
            return GetBackupFileName( fileName , fileTime , BackupDirs.Length - 1 );
        }

        /// <summary>
        /// 删除超期的文件目录，并重新创建
        /// </summary>
        /// <param name="day"></param>
        public void DeleteOverdueFiles( int day )
        {
            try
            {
                string path = _backupDir + @"\" + BackupDirs[ day ];

                if ( Directory.Exists( path ) )
                {
                    string[ ] files = Directory.GetFiles( path );
                    if ( files.Length == 0 ) return;
                    WaitCallback callback = delegate
                                                {
                                                    foreach ( var file in files )
                                                    {
                                                        try
                                                        {
                                                            File.Delete( file );
                                                        }
                                                        catch ( Exception )
                                                        { }
                                                    }
                                                };
                    ThreadPool.QueueUserWorkItem( callback , null );
                }
                else
                {
                    Directory.CreateDirectory( path );
                }
            }
            catch ( Exception ex )
            {
                LogWrapper.Logger.Error( "Eflong.KJFilesEx DeleteOverdueFiles" , ex );
            }
        }
    }

    public interface IFileBackup
    {
        void BackupFile( string fileName );

        int GetBackupDir( DateTime fileTime );

        string GetBackupFileName( string fileName , DateTime fileTime , int index );

        void DeleteOverdueFiles( int day );
    }
}